﻿#pragma once

#include <learn/dll_ext.h>
#include <learn/geom/vec.h>

#include <functional>
#include <queue>
#include <random>
#include <vector>

namespace xi
{

namespace alg
{

using namespace xi::geom;

struct EXT_SYMBOL Alg_Sampler
{
    /**
     * @brief 区间采样
     *
     * @param[in] first
     * @param[in] last
     * @return std::vector<double>
     */
    virtual std::vector<double> perform(double first, double last) const = 0;

    /**
     * @brief 参数域采样
     *
     * @param[in] uFirst
     * @param[in] uLast
     * @param[in] vFirst
     * @param[in] vLast
     * @return std::vector<Vec2>
     */
    virtual std::vector<Vec2> perform(double uFirst, double uLast, double vFirst, double vLast) const = 0;
};

struct EXT_SYMBOL Alg_Uniform_Sampler : Alg_Sampler
{
    std::size_t uCount{100};
    std::size_t vCount{100};

    /**
     * @brief 区间采样
     *
     * @param[in] first
     * @param[in] last
     * @return std::vector<double>
     */
    std::vector<double> perform(double first, double last) const override;

    /**
     * @brief 参数域采样
     *
     * @param[in] uFirst
     * @param[in] uLast
     * @param[in] vFirst
     * @param[in] vLast
     * @return std::vector<Vec2>
     */
    std::vector<Vec2> perform(double uFirst, double uLast, double vFirst, double vLast) const override;
};

struct EXT_SYMBOL Alg_Random_Sampler : Alg_Sampler
{
    std::size_t count{1000};

    /**
     * @brief 区间采样
     *
     * @param[in] first
     * @param[in] last
     * @return std::vector<double>
     */
    std::vector<double> perform(double first, double last) const override;

    /**
     * @brief 参数域采样
     *
     * @param[in] uFirst
     * @param[in] uLast
     * @param[in] vFirst
     * @param[in] vLast
     * @return std::vector<Vec2>
     */
    std::vector<Vec2> perform(double uFirst, double uLast, double vFirst, double vLast) const override;
};

struct EXT_SYMBOL Alg_PoissonDisk_Sampler : Alg_Sampler
{
    // 密度函数
    std::function<double(Vec2)> dense{[](Vec2) { return 1.0; }};
    std::size_t newPointCount{30};

    /**
     * @brief 区间采样
     *
     * @param[in] first
     * @param[in] last
     * @return std::vector<double>
     */
    std::vector<double> perform(double first, double last) const override;

    /**
     * @brief 参数域采样
     *
     * @param[in] uFirst
     * @param[in] uLast
     * @param[in] vFirst
     * @param[in] vLast
     * @return std::vector<Vec2>
     */
    std::vector<Vec2> perform(double uFirst, double uLast, double vFirst, double vLast) const override;
};

} // namespace alg

} // namespace xi
